/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.diagram.classdiagram.editpart;

import java.util.Iterator;

import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.uml2.uml.Classifier;
import org.eclipse.uml2.uml.InstanceSpecification;
import org.eclipse.uml2.uml.InstanceValue;
import org.eclipse.uml2.uml.LiteralBoolean;
import org.eclipse.uml2.uml.LiteralInteger;
import org.eclipse.uml2.uml.LiteralString;
import org.eclipse.uml2.uml.LiteralUnlimitedNatural;
import org.eclipse.uml2.uml.OpaqueExpression;
import org.eclipse.uml2.uml.PrimitiveType;
import org.eclipse.uml2.uml.Slot;
import org.eclipse.uml2.uml.StructuralFeature;
import org.eclipse.uml2.uml.Type;
import org.eclipse.uml2.uml.ValueSpecification;

import com.cea.papyrus.core.editor.ModelManager;
import com.cea.papyrus.core.editpart.GraphNodeWithSemanticEditPart;
import com.cea.papyrus.diagram.classdiagram.figures.SlotFigure;
import com.cea.papyrus.diagraminterchange2.di2.GraphNode;
import com.cea.papyrus.diagraminterchange2.di2.Uml1SemanticModelBridge;

/**
 * Control class for {@link Slot}.
 */
public class SlotEditPart extends GraphNodeWithSemanticEditPart {

	/**
	 * Creates a new SlotEditPart 
	 * @param graphNode parent of the graph node controlled by this edit part
	 * @param modelManager manager in charge of models, graphic and domain
	 */
	public SlotEditPart(GraphNode graphNode, ModelManager modelManager) {
		super(graphNode,modelManager);
	}

//	/* (non-Javadoc)
//	 * @see com.cea.papyrus.common.editpart.GraphNodeWithSemanticEditPart#createEditPolicies()
//	 */
//	/**
//	 * 
//	 */
//	@Override
//	protected void createEditPolicies(){
//		super.createEditPolicies();
//	}

	/**
	 * {@inheritDoc} 
	 */
	@Override
	protected IFigure createFigure() {
		return new SlotFigure();
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	protected Label getNameLabel() {
		return (SlotFigure)getFigure();
	}
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public Slot getUmlElement() {
		return (Slot)((Uml1SemanticModelBridge)(getGraphNode()).getSemanticModel()).getElement();
	}

//	/**
//	 * when the mole is changed.
//	 * 
//	 * @param notification 
//	 */
//	@Override
//	public void notifyChanged(Notification notification) {
//		super.notifyChanged(notification);
//	}

	/**
	 * {@inheritDoc} 
	 */
	@Override
	protected void refreshVisuals() {
		Dimension size = getGraphNode().getSize();
		Point p = getGraphNode().getPosition();
		Rectangle r = new Rectangle(p ,size);

		IFigure fig = getFigure();
		if(fig instanceof SlotFigure) {
			SlotFigure f = (SlotFigure)fig;
			StructuralFeature definingFeature = getUmlElement().getDefiningFeature();
			String name;
			if(definingFeature==null)
				name="UndefinedSlot";
			else {
				String valuesLabel = getLabels((Slot)getUmlElement());
				name = definingFeature.getName()+" = "+valuesLabel;
			}
			f.setName(name);//set the name
			f.setSlot();
		}
		((GraphicalEditPart) getParent()).setLayoutConstraint(this, fig, r);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void activate() {
		if (isActive()) {
			return;
		}
		super.activate();
		if (getUmlElement().getValues()!=null){
			Iterator<ValueSpecification> valueSpecs = getUmlElement().getValues().iterator();
			while(valueSpecs.hasNext()){
				ValueSpecification currentValueSpec = valueSpecs.next();
				((Notifier)(currentValueSpec)).eAdapters().add(_adapter);
			}
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void deactivate() {
		if (!isActive()) {
			return;
		}
		if (getUmlElement().getValues()!=null){
			Iterator<ValueSpecification> valueSpecs = getUmlElement().getValues().iterator();
			while(valueSpecs.hasNext()){
				ValueSpecification currentValueSpec = valueSpecs.next();
				((Notifier)(currentValueSpec)).eAdapters().remove(_adapter);
			}
		}
		super.deactivate();
	}


	/**
	 * Returns the label for the given Slot.
	 * @param slot the slot to display
	 * @return the label corresponding to the display of this slot.
	 */
	protected String getLabels(Slot slot){
		String result = "";
		// if no value: return
		if(slot.getValues().isEmpty())
			return result;
		// defining feature is multivalued
		if(slot.getDefiningFeature().isMultivalued()){
			Iterator<ValueSpecification> valueSpecs = slot.getValues().iterator();
			result+="[";
			while(valueSpecs.hasNext()){
				ValueSpecification currentValueSpec = valueSpecs.next();
				result+=getLabel(currentValueSpec)+", ";
			}
			result=result.substring(0, result.length()-2)+"]";
		}
		// defining feature is monovalued
		else {
			result+=getLabel((ValueSpecification)slot.getValues().get(0));
		}
		return result;
	}

	/**
	 * Returns the label for the given ValueSpecification
	 * @param valueSpecification the value specification to display
	 * @return the label corresponding to the display of this valueSpecification
	 */
	protected String getLabel(ValueSpecification valueSpecification){
		String label="";
		Type type = ((Slot)getUmlElement()).getDefiningFeature().getType();
		if (type!=null){
			String typeName = type.getName();

			if(valueSpecification instanceof OpaqueExpression){
				if(!((OpaqueExpression)valueSpecification).getBodies().isEmpty()) {
					label += ((OpaqueExpression)valueSpecification).getBodies().get(0);
				}
			}
			
			else if(type instanceof PrimitiveType){
				if("Integer".equals(typeName)){
					label += String.valueOf(((LiteralInteger)valueSpecification).getValue());
				} else if("UnlimitedNatural".equals(typeName)){
					label += String.valueOf(((LiteralUnlimitedNatural)valueSpecification).getValue());
				} else if("Boolean".equals(typeName)){
					label += String.valueOf(((LiteralBoolean)valueSpecification).isValue());
				} else /*if(typeName.equals("String"))*/ {
					label += ((LiteralString)valueSpecification).getValue();
				}
			}
			// InstanceValue
			else if(type instanceof Classifier){
				InstanceSpecification is = ((InstanceValue)valueSpecification).getInstance();
				if(is!=null)
					label += is.getLabel();
			}
		}
		return label;
	}
	
//	/**
//	 * @return 
//	 * 
//	 * @deprecated
//	 */
//	@Deprecated
//	protected SlotFigure getEnumerationLiteralFigure(){
//		return (SlotFigure)createFigure() ;
//	}
}
